🤖 هدف فصل:
در این فصل با اسکریپتنویسی شل آشنا میشوید که یکی از قدرتمندترین مهارتها در لینوکس است. یاد میگیرید چگونه کارهای تکراری را خودکار کنید، با متغیرها، شرطها، حلقهها و منوها برنامههای کاربردی بنویسید و مدیریت سیستم را به سطح بالاتری ببرید.
▍ ۱. مقدمه و مفاهیم پایه
Shell Scripting یعنی نوشتن یک سری دستورات در یک فایل متنی که بهصورت متوالی اجرا میشوند. این کار به شما امکان میدهد:
- کارهای تکراری را خودکار کنید.
- برنامههای کوچک برای مدیریت سیستم بسازید.
- دستورات پیچیده را در یک فایل ذخیره و هر زمان نیاز بود اجرا کنید.
🔑 نکته کلیدی: بهترین شلها برای اسکریپتنویسی، Bash و Ksh هستند. در این دوره روی Bash تمرکز میکنیم.
اسکریپتنویسی شل در آزمونهای LPIC و RHCSA بسیار پرتکرار است.
• پیشنیازها
- کار با خط فرمان و دستورات پایه لینوکس
- مدیریت فایلها و مجوزها
- آشنایی با ویرایشگرهای متنی (nano, vim)
▍ ۲. متغیرها و محیط شل
• متغیرهای Local و Global
🌍 Global (سراسری)
- در همه پردازشهای فرزند قابل دسترس است.
- با
export از Local به Global تبدیل میشود.
- با
printenv یا env قابل مشاهده است.
- مثال:
PATH, HOME
🏠 Local (محلی)
- فقط در همان شل قابل دسترس است.
- به پردازشهای فرزند ارثبری نمیشود.
- با
= تعریف میشود.
- با
printenv قابل مشاهده نیست.
myvar="Hello" # Local
export GLOBAL="I am global" # Global
echo $myvar # Hello
echo $GLOBAL # I am global
متغیرهای Local به شل فعلی محدود هستند، اما Global به شلهای فرزند ارثبری میشوند.
• انواع شل و فایلهای پیکربندی
- Login Shell: با ورود با نام کاربری و رمز اجرا میشود. فایلهای
/etc/profile و ~/.bash_profile (یا ~/.bash_login یا ~/.profile) اجرا میشوند.
- Interactive Shell: ترمینال جدید در محیط GUI. فایلهای
/etc/bash.bashrc و ~/.bashrc اجرا میشوند.
- Non-interactive Shell: برای اجرای اسکریپتها. فایلهای پیکربندی کمتر اجرا میشوند.
در Non-interactive Shell، /etc/profile و ~/.bash_profile اجرا نمیشوند.
• دستور alias
alias ll='ls -la'
alias # نمایش همه aliasها
unalias ll # حذف alias
▍ ۳. اصول اولیه اسکریپتنویسی
• عملگرهای اجرای چند فرمان
| عملگر | کاربرد | مثال |
; | اجرای همه دستورات (بدون شرط) | date; whoami |
&& | دستور دوم فقط در صورت موفقیت اولی | mkdir test && echo "OK" |
|| | دستور دوم فقط در صورت شکست اولی | ping 1.1.1.1 || echo "Down" |
• انتقال خروجی (Redirection) و پایپ
> بازنویسی فایل
>> افزودن به انتهای فایل
< ورودی از فایل
| خروجی فرمان اول به ورودی فرمان دوم
echo "Hello" > file.txt
echo "World" >> file.txt
cat < file.txt
ls -la | grep ".txt"
• ساختار یک اسکریپت ساده
echo "Hello, World!"
- Shebang (
#!/bin/bash) در اولین خط، مفسر را مشخص میکند.
- کامنتها با
# شروع میشوند (به جز Shebang).
- مجوز اجرا:
chmod +x script.sh
- اجرا:
./script.sh یا bash script.sh
- دیباگ:
bash -x script.sh
bash -x script.sh اسکریپت را در حالت دیباگ اجرا میکند و هر دستور را قبل از اجرا نمایش میدهد.
▍ ۴. ورودی و خروجی
• نمایش پیام با echo
- Single Quote (
'): همه چیز را خام (Literal) چاپ میکند. متغیرها و دستورات تفسیر نمیشوند.
- Double Quote (
"): متغیرها و دستورات ($(...)) تفسیر میشوند.
name="Ali"
echo "Hello $name" # Hello Ali
echo 'Hello $name' # Hello $name
• آرگومانهای خط فرمان
$0 ← نام اسکریپت
$1, $2, ... ← آرگومانها
$# ← تعداد کل آرگومانها
$@ ← همه آرگومانها به صورت جداگانه
$* ← همه آرگومانها به صورت یک رشته
• گرفتن ورودی از کاربر با read
| گزینه | کاربرد |
-p "prompt" | نمایش پیام قبل از ورودی |
-s | مخفی کردن ورودی (رمز عبور) |
-t seconds | زمان انتظار (Timeout) |
-n N | پس از N کاراکتر بدون Enter ادامه بده |
read -p "نام: " name
read -s -p "رمز: " pass
if read -t 5 -p "ورودی (۵ ثانیه): " input; then
echo "دریافت شد: $input"
else
echo "زمان تمام شد"
fi
▍ ۵. وضعیت اجرا و کد خروجی (Exit Status)
- هر فرمان پس از اجرا یک کد عددی برمیگرداند.
0 = موفقیت، غیر از ۰ = خطا.
- متغیر
$? آخرین کد خروجی را نگه میدارد.
ls /tmp
echo $? # 0 (موفق)
ls /nonexist
echo $? # 2 (خطا)
$? همیشه آخرین وضعیت خروج را نگه میدارد. از آن در شرطها و &&/|| استفاده میشود.
▍ ۶. محاسبات ریاضی
🔵 $[ ] (اعداد صحیح)
- فقط اعداد صحیح
- سریع و ساده
result=$[ 25 * 5 ]
🟢 bc (اعداد اعشاری)
- اعداد اعشاری و توابع ریاضی
- دقت با
scale کنترل میشود
echo "scale=2; 3.44 / 5" | bc
a=10; b=20
sum=$[ a + b ]
result=$(echo "scale=2; $a / $b" | bc)
▍ ۷. شرطها (test و if)
• دستور test و براکت [ ]
test condition معادل [ condition ] است.
- بررسی فایلها:
-e (وجود)، -d (دایرکتوری)، -f (فایل معمولی)، -r (خواندنی)، -w (نوشتنی)، -x (اجرایی)، -s (غیرخالی)
- مقایسه اعداد:
-eq, -ne, -gt, -lt, -ge, -le
- مقایسه رشتهها:
=, !=, -z (خالی), -n (غیرخالی)
- قدمت فایل:
-nt (جدیدتر), -ot (قدیمیتر)
[ -e file.txt ] && echo "وجود دارد"
[ 5 -gt 3 ] && echo "بزرگتر"
[ "hello" = "hello" ] && echo "برابر"
در [ ] حتماً بین براکت و شرط فاصله بگذارید.
• ساختار if
if [ شرط ۱ ]; then
دستورات (شرط ۱ درست)
elif [ شرط ۲ ]; then
دستورات (شرط ۲ درست)
else
دستورات (هیچ شرطی درست نبود)
fi
if [ -z "$1" ]; then
echo "لطفا یک آرگومان وارد کنید"
elif [ -f "$1" ]; then
echo "فایل وجود دارد"
else
echo "فایل وجود ندارد"
fi
▍ ۸. case و select
• case برای مقایسه با چند الگو
case $variable in
الگو۱)
دستورات
;;
الگو۲)
دستورات
;;
*)
دستورات پیشفرض
;;
esac
case $CHOICE in
ip) ip addr show ;;
link) ip link show ;;
exit) echo "خروج" ;;
*) echo "نامعتبر" ;;
esac
• select برای منوی عددی
PS3 پرامپت منو را مشخص میکند.
- گزینهها به صورت خودکار شمارهگذاری میشوند.
- شماره انتخابشده در
REPLY ذخیره میشود.
PS3="Select option: "
select CMD in "IP" "Link" "Exit"
do
case $REPLY in
1) ip addr show ;;
2) ip link show ;;
3) echo "خروج"; break ;;
*) echo "نامعتبر" ;;
esac
done
ترکیب select و case بهترین روش برای ایجاد منوهای حرفهای است.
▍ ۹. حلقهها (for, while, until)
• حلقه for
for var in لیست
do
دستورات با $var
done
- لیست میتواند ثابت، خروجی
seq، {1..10} یا خروجی فرمان باشد.
seq اعداد متوالی تولید میکند: seq 1 2 10 → ۱ ۳ ۵ ۷ ۹
for i in 1 2 3 4 5; do echo "Welcome $i"; done
for i in $(seq 1 5); do ping -c 1 192.168.1.$i; done
for file in /etc/passwd /etc/hosts; do cp $file /tmp/; done
• حلقههای while و until
# while: تا زمانی که شرط درست است اجرا کن
count=1
while [ $count -le 5 ]; do
echo "شمارش: $count"
((count++))
done
# until: تا زمانی که شرط نادرست است اجرا کن
count=1
until [ $count -gt 5 ]; do
echo "شمارش: $count"
((count++))
done
▍ ۱۰. اجرا در پسزمینه و مدیریت پردازش
| دستور | کاربرد |
command & | اجرا در پسزمینه |
jobs | نمایش پردازشهای پسزمینه |
fg %N | آوردن پردازش N به جلو (Foreground) |
bg %N | ادامه پردازش متوقفشده در پسزمینه |
| Ctrl+Z | متوقف کردن پردازش جاری |
| Ctrl+C | خاتمه پردازش جاری |
nohup command & | اجرا بدون وابستگی به ترمینال (ادامه پس از بستن ترمینال) |
sleep 100 & # پسزمینه
jobs -l # نمایش با PID
fg %1 # آوردن به جلو
nohup ./script.sh > log & # اجرای دائمی
💡 نکته: nohup خروجی را به nohup.out هدایت میکند مگر اینکه خلاف آن مشخص شود.
📌 نکات طلایی برای امتحان (جمعبندی نهایی)
- Shebang:
#!/bin/bash در اولین خط.
- متغیرها:
name="value" (بدون فاصله). دسترسی با $name.
- Global: با
export ساخته میشود.
- فایلهای پیکربندی:
/etc/profile (عمومی)، ~/.bash_profile (لاگین)، ~/.bashrc (اینتراکتیو).
- خروجی فرمان:
$? برای بررسی موفقیت (۰ = موفق).
- خواندن ورودی:
read -p "پیام" var، -s برای مخفی کردن، -t برای زمان.
- محاسبات:
$[ a + b ] برای اعداد صحیح، bc برای اعشاری.
- شرطها:
[ condition ] با فاصله. عملگرهای -eq, -gt, -z, =.
- if:
if [ ... ]; then ... elif ...; then ... else ...; fi
- case:
case $var in pattern1) ... ;; *) ... ;; esac
- select: ایجاد منوی عددی با
PS3 و REPLY.
- حلقهها:
for با seq، while، until.
- پسزمینه:
&، jobs، fg، bg، nohup.
✅ تمرین عملی پیشنهادی
- یک اسکریپت بنویسید که با
read نام و سن کاربر را بگیرد و پیام خوشآمدگویی چاپ کند.
- اسکریپتی بنویسید که با
case یک منوی ساده با گزینههای «تاریخ»، «کالی» و «خروج» ایجاد کند.
- با
select و case یک منوی حرفهای برای مدیریت شبکه (نمایش IP، مسیرها، ...) بسازید.
- یک حلقه
for بنویسید که اعداد ۱ تا ۱۰ را با seq تولید کرده و فقط زوجها را چاپ کند.
- یک اسکریپت طولانیمدت (مثل
ping) را با nohup در پسزمینه اجرا کنید و خروجی را در فایل ذخیره کنید.